const EMOTICON_PATH = "chrome://viecalendar/skin/images/emoticons/";
const EMOTICON_MAP = {
    "[:)]": {image: "1.gif", meaning: "happy"},
    "[:(]": {image: "2.gif", meaning: "sad"},
    "[;)]": {image: "3.gif", meaning: "winking"},
    "[:D]": {image: "4.gif", meaning: "big grin"},
    "[;;)]": {image: "5.gif", meaning: "batting eyelashes"},
    "[>:D<]": {image: "6.gif", meaning: "big hug"},
    "[:-/]": {image: "7.gif", meaning: "confused"},
    "[:x]": {image: "8.gif", meaning: "love struck"},
    "[:\">]": {image: "9.gif", meaning: "blushing"},
    "[:P]": {image: "10.gif", meaning: "tongue"},
    "[:-*]": {image: "11.gif", meaning: "kiss"},
    "[=((]": {image: "12.gif", meaning: "broken heart"},
    "[:-O]": {image: "13.gif", meaning: "surprise"},
    "[X(]": {image: "14.gif", meaning: "angry"},
    "[:>]": {image: "15.gif", meaning: "smug"},
    "[B-)]": {image: "16.gif", meaning: "cool"},
    "[:-S]": {image: "17.gif", meaning: "worried"},
    "[#:-S]": {image: "18.gif", meaning: "whew!"},
    "[>:)]": {image: "19.gif", meaning: "devil"},
    "[:((]": {image: "20.gif", meaning: "crying"},
    "[:))]": {image: "21.gif", meaning: "laughing"},
    "[:|]": {image: "22.gif", meaning: "straight face"},
    "[/:)]": {image: "23.gif", meaning: "raised eyebrow"},
    "[=))]": {image: "24.gif", meaning: "rolling on the floor"},
    "[O:-)]": {image: "25.gif", meaning: "angel"},
    "[:-B]": {image: "26.gif", meaning: "nerd"},
    "[=;]": {image: "27.gif", meaning: "talk to the hand"},
    "[:-c]": {image: "101.gif", meaning: "call me"},
    "[:)]]": {image: "100.gif", meaning: "on the phone"},
    "[~X(]": {image: "102.gif", meaning: "at wits' end"},
    "[:-h]": {image: "103.gif", meaning: "wave"},
    "[:-t]": {image: "104.gif", meaning: "time out"},
    "[8->]": {image: "105.gif", meaning: "daydreaming"},
    "[I-)]": {image: "28.gif", meaning: "sleepy"},
    "[8-|]": {image: "29.gif", meaning: "rolling eyes"},
    "[L-)]": {image: "30.gif", meaning: "loser"},
    "[:-&]": {image: "31.gif", meaning: "sick"},
    "[:-$]": {image: "32.gif", meaning: "don't tell anyone"},
    "[[-(]": {image: "33.gif", meaning: "not talking"},
    "[:O)]": {image: "34.gif", meaning: "clown"},
    "[8-}]": {image: "35.gif", meaning: "silly"},
    "[<:-P]": {image: "36.gif", meaning: "party"},
    "[(:|]": {image: "37.gif", meaning: "yawn"},
    "[=P~]": {image: "38.gif", meaning: "drooling"},
    "[:-?]": {image: "39.gif", meaning: "thinking"},
    "[#-o]": {image: "40.gif", meaning: "d'oh"},
    "[=D>]": {image: "41.gif", meaning: "applause"},
    "[:-SS]": {image: "42.gif", meaning: "nailbiting"},
    "[@-)]": {image: "43.gif", meaning: "hypnotized"},
    "[:^o]": {image: "44.gif", meaning: "liar"},
    "[:-w]": {image: "45.gif", meaning: "waiting"},
    "[:-<]": {image: "46.gif", meaning: "sigh"},
    "[>:P]": {image: "47.gif", meaning: "phbbbbt"},
    "[<):)]": {image: "48.gif", meaning: "cowboy"},
    "[:o3]": {image: "108.gif", meaning: "puppy dog eyes"},
    "[:-??]": {image: "106.gif", meaning: "I don't know"},
    "[%-(]": {image: "107.gif", meaning: "not listening"},
    "[:@)]": {image: "49.gif", meaning: "pig"},
    "[3:-O]": {image: "50.gif", meaning: "cow"},
    "[:(|)]": {image: "51.gif", meaning: "monkey"},
    "[~:>]": {image: "52.gif", meaning: "chicken"},
    "[@};-]": {image: "53.gif", meaning: "rose"},
    "[%%-]": {image: "54.gif", meaning: "good luck"},
    "[**==]": {image: "55.gif", meaning: "flag"},
    "[(~~)]": {image: "56.gif", meaning: "pumpkin"},
    "[~O)]": {image: "57.gif", meaning: "coffee"},
    "[*-:)]": {image: "58.gif", meaning: "idea"},
    "[8-X]": {image: "59.gif", meaning: "skull"},
    "[=:)]": {image: "60.gif", meaning: "bug"},
    "[>-)]": {image: "61.gif", meaning: "alien"},
    "[:-L]": {image: "62.gif", meaning: "frustrated"},
    "[[-O<]": {image: "63.gif", meaning: "praying"},
    "[$-)]": {image: "64.gif", meaning: "money eyes"},
    "[:-\"]": {image: "65.gif", meaning: "whistling"},
    "[b-(]": {image: "66.gif", meaning: "feeling beat up"},
    "[:)>-]": {image: "67.gif", meaning: "peace sign"},
    "[[-X]": {image: "68.gif", meaning: "shame on you"},
    "[\\:D/]": {image: "69.gif", meaning: "dancing"},
    "[>:/]": {image: "70.gif", meaning: "bring it on"},
    "[;))]": {image: "71.gif", meaning: "hee hee"},
    "[:-@]": {image: "76.gif", meaning: "chatterbox"},
    "[^:)^]": {image: "77.gif", meaning: "not worthy"},
    "[:-j]": {image: "78.gif", meaning: "oh go on"},
    "[(*)]": {image: "79.gif", meaning: "star"},
    "[o->]": {image: "72.gif", meaning: "hiro"},
    "[o=>]": {image: "73.gif", meaning: "billy"},
    "[o-+]": {image: "74.gif", meaning: "april"},
    "[(%)]": {image: "75.gif", meaning: "yin yang"}
};
const SPECHARS_REGEX = /(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\^|\$)/g;

function TextDecoder() {
    this.decode = function(text) {
        text = escapeHtml(text);
        text = decodeBBCode(text);
        text = decodeEmoticon(text);
        
        return text;
    }
    
    function escapeHtml(text) {
        text = text.replace(/&/g, '&amp;');
        text = text.replace(/'/g, '&apos;');
        text = text.replace(/"/g, '&quot;');
        text = text.replace(/\</g, '&lt;');
        text = text.replace(/>/g,'&gt;');
        
        return text;
    }
    
    function escapeRegExp(text) {
        return text.replace(SPECHARS_REGEX, '\\$1');
    }
    
    function decodeBBCode(text) {
        // \r\n, [b], [i], [u], [url], [color]
        text = text.replace(/(\r)?\n/gi, "<html:br/>");
        text = text.replace(/\[br\]/gi, "<html:br/>");
        text = text.replace(/\[b\]/gi, "<html:b>");
        text = text.replace(/\[\/b\]/gi, "</html:b>");
        text = text.replace(/\[i\]/gi, "<html:i>");
        text = text.replace(/\[\/i\]/gi, "</html:i>");
        text = text.replace(/\[u\]/gi, "<html:u>");
        text = text.replace(/\[\/u\]/gi, "</html:u>");
        text = text.replace(/\[url\](.+)\[\/url\]/gi, "<html:a href='$1' target='_blank'>$1</html:a>");
        text = text.replace(/\[url=(.+)\](.+)\[\/url\]/gi, "<html:a href='$1' target='_blank'>$2</html:a>");
        text = text.replace(/\[color=(.+)\](.+)\[\/color\]/gi, "<html:span style='color: $1'>$2</html:span>");
        
        return text;
    }
    
    function decodeEmoticon(text) {
        for(symbol in EMOTICON_MAP) {
            var src = EMOTICON_PATH + EMOTICON_MAP[symbol].image;
            var alt = "[" + EMOTICON_MAP[symbol].meaning + "]";
            symbol = escapeHtml(symbol);
            symbol = escapeRegExp(symbol);
            text = text.replace(new RegExp(symbol, "gi"), "<image src='" + src + "' tooltiptext='" + alt + "'/>");
        }
        
        return text;
    }
}